package cn.cqsztech.arithmetic;

import cn.cqsztech.vo.Student;

/**
 * 用位操作替换原始的加减乘除方法
 * ccmars
 * 2022/3/10
 **/
public class MathBitOperationReplacer {
    /**
     * a+b 可以拆成a^b + a&b<<1
     * 一直a^b的结果在^上两数进位的数直到没有进位
     * 也就是a&b<<1 == 0
     *
     * @param a
     * @param b
     * @return
     */
    public static int add(int a, int b) {
        int sum = a;
        while (b != 0) {
            sum = a ^ b;
            b = (a & b) << 1;
            a = sum;
        }
        return sum;
    }

    /**
     * 减法 加上相反数 相反数即取反+1的数 也就是补码
     *
     * @param a
     * @param b
     * @return
     */
    public static int minus(int a, int b) {
        return add(a, negative(b));
    }

    /**
     * 用位操作实现乘法
     * 利用二进制的乘法a*b=a*b的最右边一位开始然后a左移一位，然
     *
     * @param a
     * @param b
     * @return
     */
    public static int multiply(int a, int b) {
        int multi = 0;
        while (b != 0) {
            if ((b & 1) != 0) {
                multi = add(multi, a);
            }
            b = b >>> 1;
            a = a << 1;
        }
        return multi;
    }

    /**
     * 整数的除法
     * 思路是将负数换算为正数，进行正数的除发
     * 利用乘法的特性分别找到b的最大的2的n次方的数据小于a那么那一位上一定是1
     * 再用a-这个2的n次方找到剩下的最大的那个2的m次方
     * 直到a-2'?次方比b还小
     * 为了防止溢出风险b左移操作改成a右移操作
     *
     * @param a
     * @param b
     * @return
     */
    public static int div(int a, int b) {
        int result = 0;
        boolean isNeg = isNeg(a) == isNeg(b);
        a = isNeg(a) ? negative(a) : a;
        b = isNeg(b) ? negative(b) : b;
        for (int i = 30; i >= 0; i = minus(i, 1)) {
            if ((a >> i) >= b) {
                result |= 1 << i;
                a = minus(a, (b << i));
            }
        }
        return isNeg ? result : negative(result);
    }

    /**
     * 真正的除法包装
     *
     * @param a
     * @param b
     * @return
     */
    public static int divide(int a, int b) {
        if (a == Integer.MIN_VALUE && b == Integer.MIN_VALUE) {
            return 1;
        }
        if (b == Integer.MIN_VALUE) {
            return 0;
        }
        if (a == Integer.MIN_VALUE) {
            if (b == negative(1)) {
                return Integer.MAX_VALUE;
            } else {
                int c = div(a + 1, b);
                int multiply = multiply(b, c);
                int minus = minus(a, multiply);
                int div = div(minus, b);
                return add(c, div(minus(a, multiply(b, c)), b));
            }
        }
        return div(a, b);
    }

    /**
     * 判断是否是负数
     *
     * @param a
     * @return
     */
    public static boolean isNeg(int a) {
        return a < 0;
    }

    /**
     * 获取a的相反数@Integer.MIN_VALUE 不生效
     *
     * @param a
     * @return
     */
    public static int negative(int a) {
        if (a == Integer.MIN_VALUE) {
            return Integer.MAX_VALUE;
        }
        return ~a + 1;
    }

    public static final char UNDERLINE = '_';

    public static String underlineToCamel(String param) {

        String temp = param.toLowerCase();
        int len = temp.length();
        StringBuilder sb = new StringBuilder(len);
        for (int i = 0; i < len; i++) {
            char c = temp.charAt(i);
            if (c == UNDERLINE) {
                if (++i < len) {
                    sb.append(Character.toUpperCase(temp.charAt(i)));
                }
            } else {
                sb.append(c);
            }
        }
        return sb.toString();
    }

    public static void main(String[] args) {
        System.out.println(underlineToCamel("my_name_"));

        System.out.println(1 == new Student().getAge());
        for (int i = 0; i < 100_0000; i++) {
            int a = (int) (Math.random() * Integer.MAX_VALUE);
            int b = -(int) (Math.random() * Integer.MAX_VALUE);
            if (add(a, b) != (a + b) ^ minus(a, b) != a - b ^ multiply(a, b) != a * b ^ divide(a, b) != a / b) {
                System.out.println("error!");
            }
        }
        System.out.println("success");
    }


}
